package com.yh.eval;

import androidx.appcompat.app.AppCompatActivity;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import com.yh.util.AmapLocationUtils;
import com.yh.util.Config;
import com.yh.util.FloatWindow;
import com.yh.util.PowerUtil;
import com.yh.util.ShellUtils;
import com.serial.opt.UartWorkerCH;
import com.serial.port.ByteUtils;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;

import android_serialport_api.Command;

/**
 * 计价器功能通信与应用main
 */
public class MainActivity extends AppCompatActivity {

    private static final int WHAT_PRINT_STATUS = 110;
    private BusModel mBusModel;
    final String TAG = getClass().getSimpleName();
    public static final int STATUES_INIT = 1;
    public static final int STATUES_START = 2;
    public static final int STATUES_PAUSE = 3;
    public static final int STATUES_END = 4;
    ExecutorService mExecutor;

    private int mCurrentStatus = 0;
    private boolean isToast4G = true;
    private boolean isCheckStatus = true;

    private TextView mTv, mPrintStatus, mAccStatus;
    private LinearLayout mLy;
    private TextView mTVCh3Opt;
    private UartWorkerCH mWorkCh2;
    private UartWorkerCH mWorkCh3;
    private int mCh3Opt;
    private boolean isPause;
    private FloatWindow mFloatWindow;
    UsbBroadcastReceiver usbReceiver;
    private SimCardStateReceiver simCardRecei;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        mTv = findViewById(R.id.tv_statues);
        mLy = findViewById(R.id.ly_datas);
        mPrintStatus = findViewById(R.id.tv_print_status);
        mAccStatus = findViewById(R.id.tv_acc_status);
        mExecutor = createThreadPool(true);
        registerUsbReceive();
        AmapLocationUtils.getInstance().init(getApplicationContext());
        mHandler.postDelayed(()->{
            openCommonUart();
            setReceiveEvalDataLs();
            /*
             mHandler.sendEmptyMessageDelayed(WHAT_PRINT_STATUS, 1000);
              此处发延时获取，设备重启后串口会有打开异常
java.lang.UnsatisfiedLinkError: dlopen failed: "/data/app/com.ilin.atelec-yFS7XZYH57HfSsMf7wg9PA==/lib/arm/libserial_port.so" has bad ELF magic
             */
        }, 2000);
        setSwitchLs();
        // echo 180 > /sys/class/backlight/backlight/brightness
        ShellUtils.execShellCmd("settings put system screen_brightness 150"); // 210 会闪屏

        findViewById(R.id.tv_receive).setOnClickListener(v -> {
            isToast4G = !isToast4G;
            Toast.makeText(this, "show =" +isToast4G, Toast.LENGTH_SHORT).show();
        });
    //    startConnectLog();
    }

    private void registerUsbReceive() {
        usbReceiver = new UsbBroadcastReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        filter.addAction("android.hardware.usb.action.USB_STATE");
        registerReceiver(usbReceiver, filter);
        //  ShellUtils.execShellCmd("getprop ril.yuga.iccid")
        System.out.println("MainActivity.registerUsbReceive " + Build.SERIAL);

        simCardRecei = new SimCardStateReceiver();
        IntentFilter filter2 = new IntentFilter();
        // 这个监听不到Ready状态，SDK内部也监听不到
        filter2.addAction("android.intent.action.SIM_STATE_CHANGED");
        filter2.addAction("android.intent.action.SIM_REGISTING");
        registerReceiver(simCardRecei, filter2);
    }


    // 空车开关
    private void setSwitchLs() {
        Switch sw = findViewById(R.id.switch1);
        String gpio117 = ShellUtils.execShellCmd("cat /sys/class/gpio/gpio117/value");
        String gpio116 = ShellUtils.execShellCmd("cat /sys/class/gpio/gpio116/value");
        System.out.println("MainActivity.setSwitchLs gpio117 = " + gpio117 + ", io116 = " + gpio116);
        sw.setOnCheckedChangeListener((buttonView, isChecked) -> {
            new Thread(() -> {
                String gpio117i = ShellUtils.execShellCmd("cat /sys/class/gpio/gpio117/value");
                String gpio116i = ShellUtils.execShellCmd("cat /sys/class/gpio/gpio116/value");
                System.out.println("MainActivity.getSwitchLs gpio117 = " + gpio117i + ", io116 = " + gpio116i);
                if (isChecked){
                    try {
                        ShellUtils.echo(new String[]{"echo 0 > /sys/class/gpio/gpio117/value"});
                        Thread.sleep(300);
                        ShellUtils.echo(new String[]{"echo 1 > /sys/class/gpio/gpio116/value"});
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                else {
                    try {
                        ShellUtils.echo(new String[]{"echo 1 > /sys/class/gpio/gpio117/value"});
                        Thread.sleep(300);
                        ShellUtils.echo(new String[]{"echo 0 > /sys/class/gpio/gpio116/value"});
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        });
    }

    Handler mHandler = new Handler(Looper.getMainLooper()){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
//            System.out.println("handleMessage.msg = " + msg);
            if (msg.what == IAtCmd.W_MSG_DISPLAY){
                if (msg.obj == null) return;
                String receiveData = msg.obj.toString();
                TextView tv = (TextView) LayoutInflater.from(getBaseContext()).inflate(R.layout.item_data, null);
                mLy.addView(tv, 0);
                Calendar cl = Calendar.getInstance(TimeZone.getTimeZone("GMT-0:00"));
                tv.setText(dateToString(cl.getTime(), "HH:mm:ss "));
                tv.append(receiveData);
                if (mLy.getChildCount() > 20){
                    mLy.removeViewAt(20);
                }
                checkStatues(receiveData);
            } else if (msg.what == WHAT_PRINT_STATUS) {
                String st = ShellUtils.execShellCmd("cat /sys/class/gpio/gpio73/value");
//                System.out.println("MainActivity.handleMessage 打印机状态 = [" + st + "]");
                mPrintStatus.setText(st);
                // 钥匙开关状态
                String acc = ShellUtils.execShellCmd("cat /sys/class/gpio/gpio75/value");
                System.out.println("MainActivity.handleMessage acc状态 = [" + acc + "]");
                sleepOrWake("1".equals(acc));
                mAccStatus.setText(acc);
                removeMessages(WHAT_PRINT_STATUS);
                if (isCheckStatus) sendEmptyMessageDelayed(WHAT_PRINT_STATUS, 2000);
            } else if (msg.what == 120) {
                try {
                    mWorkCh3.getWriter().writeData(ByteUtils.hexStr2Byte(msg.obj.toString()));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    };

    boolean mWakeup = true;
    void sleepOrWake(boolean isSleep){
        if (mWakeup == !isSleep){
            return;
        }
        if (isSleep){
//            ShellUtils.execShellCmd("input keyevent 26");
            ShellUtils.execShellCmd("input keyevent KEYCODE_POWER");
            ShellUtils.execEcho("echo 0 > /sys/class/gpio/gpio70/value"); // 按钮背光
//            ShellUtils.execEcho("echo 0 > /sys/class/gpio/gpio11/value"); // LCD 背光使能
        }else {
//            ShellUtils.execShellCmd("input keyevent 26");  // 电源键
            ShellUtils.execShellCmd("input keyevent KEYCODE_WAKEUP");
            ShellUtils.execEcho("echo 1 > /sys/class/gpio/gpio70/value");
        }
        mWakeup = !isSleep;
    }

    private void checkStatues(String result) {
        if (result.startsWith("55AA") && result.endsWith("55AA")
            && result.length() > 16 && result.startsWith("E4", 14)) {
//        Thread.sleep(50L);
            mBusModel.write(Command.CMD_END_RESPONSE);
            Log.e(TAG, "checkStatues: 营运数据应答");
        }
    }

    /**
     * 把日期转换为字符串
     */
    public String dateToString(Date date, String format) {
        String result = "";
        if (null != date) {
            SimpleDateFormat formater = new SimpleDateFormat(format);
            try {
                result = formater.format(date);
            } catch (Exception e) {
                Log.e("DataUtils", "时间格式转换异常: date:" + date + ", format:" + format);
            }
        }
        return result;
    }

    @Override
    public void onBackPressed() {
//        super.onBackPressed();
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
//        createFlowView(100, 100);
    }

    public void createFlowView(int w, int h){
        if (mFloatWindow == null) {
            // 创建一个新的悬浮窗
            mFloatWindow = new FloatWindow(getApplicationContext(), w, h);
            // 设置悬浮窗的布局内容
            mFloatWindow.setLayout(R.layout.flow_view);
            mFloatWindow.show();
            Log.i(TAG, "createFlowView: 启动浮窗侦测");
        }
    }

    void closeUsb(){
        /*
        如果只想关闭USB调试功能，可以：
setprop persist.sys.usb.config mtp
如果只想关闭USB文件传输功能，可以：
setprop persist.sys.usb.config adb
禁用USB
setprop persist.sys.usb.config none
         */
        ShellUtils.execShellCmd("setprop persist.sys.usb.config mtp");
    }

    public void onClick(View v){
        if (v.getId() == R.id.btn1){
            initStatus();
//            closeUsb();
        }
        else if (v.getId() == R.id.btnStart){
            startActivity(new Intent(this, MainSActivity.class));
            mBusModel.write(Command.CMD_START);
            changeStatus(STATUES_START);
        }
        else if (v.getId() == R.id.btnPause){
            ((TextView)v).setText(mCurrentStatus == STATUES_START ? "continue" : "pause");
            mBusModel.write(mCurrentStatus == STATUES_START ? Command.CMD_PAUSE : Command.CMD_CONTINUE);
            changeStatus(mCurrentStatus == STATUES_START ? STATUES_PAUSE : STATUES_START);
        }
        else if (v.getId() == R.id.btnEnd){
            mBusModel.write(Command.CMD_END);
            changeStatus(STATUES_END);
        }
        else if (v.getId() == R.id.btn_ser2_open){
            openCH2();
        }
        else if (v.getId() == R.id.btn_ser2_send){
            if (mWorkCh2 != null) {
                try {
                    String writeData = ((EditText)findViewById(R.id.edt_ser2)).getText().toString();
//                    mWorkCh2.getWriter().writeData(ByteUtils.hexStr2Byte("5a6a7a"));
                    mWorkCh2.getWriter().writeData(ByteUtils.hexStr2Byte(writeData));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }else{
//                ShellUtils.execShellCmd(" input keyevent 26");
//                v.postDelayed(()->{
//                    ShellUtils.execEcho("echo 0 > /sys/class/gpio/gpio70/value");
//                    Intent intent = new Intent("android.intent.action.askillsdk.ota");
//                    // 未启动的包
//                    intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
//                    intent.addFlags(0x01000000);
//                    intent.setComponent(new ComponentName("com.ota.skillsdk", "com.ota.skillsdk.SkillSdkOtaReceiver"));
//                    getApplicationContext().sendBroadcast(intent);
//                    Log.i(TAG, "onKeyDown: 发送ota检测升级广播3");
//                }, 3000);
                Toast.makeText(this, "未打开", 0).show();
            }
        }
        else if (v.getId() == R.id.btn_ser3_open) {
            openCH3();
        } else if (v.getId() == R.id.btn_ser31_send) {
            workCh3SendData(1, ((EditText)findViewById(R.id.edt_ser31)).getText().toString());
        }else if (v.getId() == R.id.btn_ser32_send) {
            workCh3SendData(2, ((EditText)findViewById(R.id.edt_ser32)).getText().toString());
        }else if (v.getId() == R.id.btn_ser33_send) {
            workCh3SendData(3, ((EditText)findViewById(R.id.edt_ser33)).getText().toString());
        } else if (v.getId() == R.id.btn_print) {
            sendPrintCmd();
        } else if (v.getId() == R.id.btn_settings) {
            Intent intent = new Intent();
            intent.setAction("android.intent.action.VIEW");
            ComponentName component = new ComponentName("com.android.settings", "com.android.settings.Settings");
            intent.setComponent(component);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.putExtra("extra_prefs_show_button_bar", true);
            intent.putExtra("extra_prefs_set_next_text", "完成");
            intent.putExtra("extra_prefs_set_back_text", "返回");
            startActivity(intent);
        }else if (v.getId() == R.id.btn_getLocation){
            try{
                // 启动获取定位app
//                ShellUtils.execShellCmd("am start com.fanweilin.coordinatemap/com.fanweilin.coordinatemap.Activity.MainMapsActivity");
                // 重启GPS 服务
                ShellUtils.execShellCmd("setprop persist.boot.noril2 true");
            }catch (Exception e){
                Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
                e.printStackTrace();
            }
        }else if (v.getId() == R.id.btn_getAdb){
            // 0 关，1开
//            String adbStatus = ShellUtils.execShellCmd("getprop persist.service.adb.enable");
//            Toast.makeText(this, "0".equals(adbStatus)? "adb已关":"adb开", Toast.LENGTH_SHORT).show();
            startConnectLog();
        }
        else if (v.getId() == R.id.btn_4gEtc) {
            startActivity(new Intent(this, TF4GActivity.class));
        }
        if (v.getId() == R.id.btn_L100){
//            ShellUtils.execShellCmd("settings put system screen_brightness 100");
            ShellUtils.execShellCmd("setprop persist.service.adb.enable 0"); // 关adb调试
//            ShellUtils.execEcho("echo host > /sys/devices/platform/ff2c0000.syscon/ff2c0000.syscon:usb2-phy@100/otg_mode");
//            ShellUtils.execShellCmd("setprop sys.usb.config adb"); set this will restart adb
        }
        if (v.getId() == R.id.btn_L120){
//            ShellUtils.execShellCmd("settings put system screen_brightness 120");
            ShellUtils.execShellCmd("setprop persist.service.adb.enable 1"); // 开adb调试
        }
        if (v.getId() == R.id.btn_L150){
            ShellUtils.execShellCmd("settings put system screen_brightness 150");
        } else if (v.getId() == R.id.btn_L190) {
            ShellUtils.execShellCmd("settings put system screen_brightness 190");
        }else if (v.getId() == R.id.btnAcc){
            sendCheckOtaBroadcast(1); // btn acc
        }else if (v.getId() == R.id.btnPPP){
            sendCheckOtaBroadcast(3); // btn ppp
        }else if (v.getId() == R.id.btnStop){
            sendCheckOtaBroadcast(4); // btn stop
            ShellUtils.execShellCmd("am start com.ilin.test"); // 跳转到下线检测app
        }
    }

    long lastConnect;
    public void startConnectLog(){
        if (lastConnect > 0 && System.currentTimeMillis() - lastConnect < 3000){
            Toast.makeText(this, "收集log 间隔时间太短", 1).show();
            return;
        }
        long time = System.currentTimeMillis()/1000;
        String rootP = Environment.getExternalStorageDirectory().getAbsolutePath() + "/radio";
        File fl = new File(rootP);
        if (!fl.exists()){
            fl.mkdirs();
        }
//        String logPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/radio-log-" +time+".log";
        String logPath = rootP + "/radio-log-" +time+".log";

        //    Process process = Runtime.getRuntime().exec("logcat -d -b radio -f " + logPath);
//            new Thread(()-> {
                try {
                Process process = Runtime.getRuntime().exec("logcat -d -b radio -v time -f " + logPath);
                process.waitFor();
                Toast.makeText(this, "开始收集radio log", 1).show();
                } catch (IOException | InterruptedException e) {
                    e.printStackTrace();
                }
//            }).start();
        lastConnect = System.currentTimeMillis();
    }

    private ExecutorService createThreadPool(boolean isCheck) {
        if (isCheck){
            if (mExecutor != null) return mExecutor;
        }
        //
        // 不能用 new LinkedBlockingQueue<>() 默认构造函数，时间久了可能会出现OOM
        return new ThreadPoolExecutor(3, 3, 0L,
                java.util.concurrent.TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(50));
    }

    private void sendPrintCmd(){
        isCheckStatus = true;
        mHandler.sendEmptyMessageDelayed(WHAT_PRINT_STATUS, 1000);
        if (mWorkCh3 == null){
            Toast.makeText(this, "未打开Ch3", 0).show();
            return;
        }
//        mTVCh3Opt = findViewById(R.id.tv_result_);
        mCh3Opt = 4;
        mExecutor.execute(()->{
            try {
                ShellUtils.execEcho("echo 0 > /sys/class/gpio/gpio64/value");
                Thread.sleep(200);
                ShellUtils.execEcho("echo 0 > /sys/class/gpio/gpio65/value");  // 11 打印
                Thread.sleep(200);
                String data = Config.getSPIData().replace(" ", "");
                byte[] bytes = ByteUtils.hexStr2Byte(data);
                mWorkCh3.getWriter().writeData(bytes);
                System.out.println("MainActivity.sendPrintCmd 开始打印……");
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    private void workCh3SendData(int opt, String data) {
        if (mWorkCh3 != null) {
            if (opt == 1){
                ShellUtils.execEcho("echo 1 > /sys/class/gpio/gpio64/value");
                ShellUtils.execEcho("echo 1 > /sys/class/gpio/gpio65/value"); // 00 对应背面第1个串口
                mTVCh3Opt = findViewById(R.id.tv_result_ser31);
            }else if (opt == 2){
                ShellUtils.execEcho("echo 1 > /sys/class/gpio/gpio64/value");
                ShellUtils.execEcho("echo 0 > /sys/class/gpio/gpio65/value"); // 01 对应背面第2个串口
                mTVCh3Opt = findViewById(R.id.tv_result_ser32);
            }else if (opt == 3){
                ShellUtils.execEcho("echo 0 > /sys/class/gpio/gpio64/value");
                ShellUtils.execEcho("echo 1 > /sys/class/gpio/gpio65/value");  // 10 对应背面第4个串口
                mTVCh3Opt = findViewById(R.id.tv_result_ser33);
            }else {
                Log.w(TAG, "workCh3SendData: 不支持的opt = " + opt );
                return;
            }
            mCh3Opt = opt;
            Message msg = mHandler.obtainMessage();
            msg.what = 120;
            msg.obj = data;
            mHandler.sendMessageDelayed(msg, 20);

//            mExecutor.execute(()->{
//                try {
//                    Thread.sleep(50);
//                    mWorkCh3.getWriter().writeData(ByteUtils.hexStr2Byte(data));
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
//            });
        }else Toast.makeText(this, "Ch3未打开", Toast.LENGTH_SHORT).show();
    }

    void changeStatus(int statu){
        mCurrentStatus = statu;
        switch (statu){
            case STATUES_INIT:
                mTv.setText("就绪");
                break;
            case STATUES_START:
                mTv.setText("运行中");
                break;
            case STATUES_PAUSE:
                mTv.setText("暂停");
                break;
            case STATUES_END:
                mTv.setText("结束");
                break;
        }
    }

    @Override
    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
        System.out.println("onKeyLongPress keyCode = " + keyCode + ", event = " + event);
        return super.onKeyLongPress(keyCode, event);
    }


    @Override
    protected void onResume() {
        super.onResume();
        isPause = false;
        if (mBusModel != null) mBusModel.startCommunicate();
        if (mFloatWindow != null) mFloatWindow.close();
        mHandler.sendEmptyMessageDelayed(WHAT_PRINT_STATUS, 2800);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mFloatWindow != null && !mFloatWindow.isShow()) mFloatWindow.show();
        isPause = true;
        if (mBusModel != null) mBusModel.stopCommunicate();
   //     mHandler.removeMessages(WHAT_PRINT_STATUS);
    }

    // 打开计价串口
    void openCommonUart(){
        try {
            if (null == mBusModel) {
                mBusModel = BusModel.getInstance(this);
            }
            mBusModel.init(Config.SERIAL_CH1, Config.BATE);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 设置接受计量版数据监听
    void setReceiveEvalDataLs(){
        mBusModel.setListener(data -> {
            mHandler.sendMessage(mHandler.obtainMessage(IAtCmd.W_MSG_DISPLAY, data));
        });
    }

    private void openCH2(){
        try {
            mWorkCh2 = new UartWorkerCH(Config.SERIAL_CH2, Config.BATE_CH, 0, "CH2"); // 对应背面第3个串口
            mWorkCh2.setOnReceiveListener(data -> {
                mHandler.post(()->{
                    ((TextView)findViewById(R.id.tv_result_ser2)).setText(data);
                });
            });
            mWorkCh2.startCommunicate();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void openCH3(){
        try {
            mWorkCh3 = new UartWorkerCH(Config.SERIAL_CH3, Config.BATE_CH, 0, "CH3");
            mWorkCh3.setOnReceiveListener(data -> {
                mHandler.post(()->{
                    System.out.println("CH3.Opt" + mCh3Opt + " receive = " + data);
                    if (mTVCh3Opt != null) mTVCh3Opt.setText(data);
                });
            });
            mWorkCh3.startCommunicate();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void initStatus() {
        mBusModel.write(Command.CMD_INIT);
        changeStatus(STATUES_INIT);
        mLy.removeAllViews();
    }

    void testSaveFile(){
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            // 外部存储可以读取和写入
            System.out.println("MainActivity.testSaveFile 外部存储可以读取和写入");
        } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            // 外部存储只读
            System.out.println("MainActivity.testSaveFile 外部存储只读");
        } else {
            // 外部存储不可用
            System.err.println("MainActivity.testSaveFile 外部存储不可用");
        }
//        String rootPath = getFilesDir().getPath();
        String rootPath = Environment.getExternalStorageDirectory().getPath();
        System.out.println("MainActivity.testSaveFile " + rootPath);
        File file = new File(rootPath + String.format("/data%s.json", System.currentTimeMillis()/1000));
        // 要写入的字符串
        String jsonString = "{\"name\": \"John\", \"age\": 32}";

        try {
            // 使用 BufferedWriter 将字符串写入文件
//            BufferedWriter writer = new BufferedWriter(new FileWriter(file));
//            writer.write(jsonString);
//            System.out.println("数据已写入文件: " + file.getAbsolutePath());
//            writer.flush();

            FileOutputStream fos = null;
            fos = new FileOutputStream(file);
            //将buf中的数据写入fos
            fos.write(jsonString.getBytes());
            //将fos的数据保存到内核缓冲区
            //不能确保数据保存到物理存储设备上，如突然断点可能导致文件未保存
            fos.flush();
            //将数据同步到达物理存储设备
            FileDescriptor fd = fos.getFD();
            fd.sync();
            System.out.println("数据已写入磁盘，文件: " + file.getAbsolutePath());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        System.out.println("onKeyDown keyCode = " + keyCode + ", event = " + event);
        int code = event.getScanCode();
        if (248 <= code && code <= 255){
            myKeyCodeDown(code);
        }
        if (keyCode == 10){
            initStatus();
        }
        if (keyCode == 20){
            mBusModel.write(Command.CMD_START);
        }
//        if (keyCode == 79){ // 声音开关
        else if (keyCode == 100){
            sendCheckOtaBroadcast(2); // key100
        }else if (keyCode == 8888){
            if (mBusModel != null) mBusModel.stopCommunicate();
            if (mBusModel != null) mBusModel.stop();
            System.out.println("MainActivity.onKeyDown 进入休眠低功耗");
            PowerUtil.intoSleep(this, 2000);
        }else if (keyCode == 777){
            testSaveFile();
        }

        return super.onKeyDown(keyCode, event);
    }

    /**
     * 发送OTA检测升级广播
     * @param opt 操作类型
     * 1 用户手动检测升级，亮屏情况下，会有下载进度Toast提示
     * 2 休眠后检测升级，熄屏情况下
     * 3 暂停升级，如在下载ota文件，继续下载到完成为止
     * 4 终止升级，如在下载ota文件, 终止本次下载
     */
    private void sendCheckOtaBroadcast(int opt) {
        Intent intent = new Intent("android.intent.action.askillsdk.ota");
        intent.addFlags(0x01000000);
        intent.setComponent(new ComponentName("com.ota.skillsdk", "com.ota.skillsdk.SkillSdkOtaReceiver"));
        intent.putExtra("option", opt);
        getApplicationContext().sendBroadcast(intent);
        Log.i(TAG, "onKeyDown: 发送ota检测升级广播");
    }

    String[] keyMaps = new String[]{"empty", "go", "stop", "pay", "set", "dollar 10", "dollar 1", "print",};
    // 自定义按键，8个
    void myKeyCodeDown(int code){
        switch (code){
            case 248: // empty

                break;
            case 249: // go

                break;
            case 250: // stop

                break;
            case 251: // pay

                break;
            case 252: // set

                break;
            case 253: // dollar 10

                break;
            case 254: // dollar 1

                break;
            case 255: // print

                break;
        }
        Toast.makeText(this, keyMaps[code - 248], Toast.LENGTH_SHORT).show();
    }

    public static class UsbBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            System.out.println("UsbBroadcastReceiver.onReceive action = " + action);
            if ("android.hardware.usb.action.USB_STATE".equals(action)) {
                boolean connected = intent.getExtras().getBoolean("connected");
                if (connected) {
                    // 处理USB连接事件
                    System.out.println("UsbBroadcastReceiver.onReceive USB 连上");
                    // 0 关，1开
                    String adbStatus = ShellUtils.execShellCmd("getprop persist.service.adb.enable");
//                    if (!isOpenAdb){
//                        ShellUtils.execEcho("echo host > /sys/devices/platform/ff2c0000.syscon/ff2c0000.syscon:usb2-phy@100/otg_mode");
//                    }else
                        Toast.makeText(context, "接入了USB数据线，注意数据安全！", Toast.LENGTH_SHORT).show();
                } else {
                    // 处理USB断开事件
                    System.out.println("UsbBroadcastReceiver.onReceive USB 断开");
                    Toast.makeText(context, "拔出了USB数据线", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }

    public class SimCardStateReceiver extends BroadcastReceiver {
        long lastRestTime = 0;
        @Override
        public void onReceive(Context context, Intent intent) {

            String action = intent.getAction();
            System.out.println("SimCardStateReceiver.onReceive action = " + intent);
            if ("android.intent.action.SIM_REGISTING".equals(action)){
                if (lastRestTime > 0 && System.currentTimeMillis() - lastRestTime < 5000){
                    System.err.println("SimCardStateReceiver.onReceive registing from self, return " );
                    lastRestTime = System.currentTimeMillis();
                    return;
                }
                ShellUtils.execShellCmd("setprop persist.boot.noril true");
                Toast.makeText(context, "SIM卡Ready，重启4G服务联网 ", Toast.LENGTH_LONG).show();
                lastRestTime = System.currentTimeMillis();
            }else
            if ("android.intent.action.SIM_STATE_CHANGED".equals(action)) { // TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED
//                这个一直为null, SDK也是
                String state = intent.getStringExtra("android.telephony.extra.SIM_STATE");
                System.out.println("SimCardStateReceiver.onReceive state = " + state);
           //     Toast.makeText(context, "SIM.state = " +state, Toast.LENGTH_SHORT).show();
//                if (TelephonyManager.SIM_STATE_ABSENT == state) {
//                    // SIM卡被移除
//                    Log.d("SimCardStateReceiver", "SIM card removed");
//                }
            }
        }
    }

}